package com.itheima.service.Impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.dto.DishDto;
import com.itheima.exception.CustomException;
import com.itheima.mapper.CategoryDao;
import com.itheima.mapper.DishDao;
import com.itheima.mapper.DishFlavorDao;
import com.itheima.pojo.Category;
import com.itheima.pojo.Dish;
import com.itheima.pojo.DishFlavor;
import com.itheima.result.R;
import com.itheima.service.DishDtoService;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;


import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: 斌
 * @DateTime: 2023年02月08日  23:43:19
 * @Description: com.itheima.service.Impl
 * @Version: 1.0
 */
@Slf4j
@Service
public class DishDtoServiceImpl implements DishDtoService {
    @Autowired
    private DishDao dishDao;
    @Autowired
    private DishFlavorDao dishFlavorDao;
    @Autowired
    private CategoryDao categoryDao;
    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 新增菜品
     * @param dishDto
     * @return
     */
    @Override
    public R saveDish(DishDto dishDto) {
        log.info("前端传回的数据:{}",dishDto.toString());


        //增删改操作把之前存Redis的数据删掉，保证数据的同步
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);


        int dishResult = dishDao.insert(dishDto);
        //口味信息
        List<DishFlavor> flavors = dishDto.getFlavors();
        //  获取dishId
        Long dishId = dishDto.getId();
        log.info("菜品Id：{}",dishId);
        int flavorResult = 0;
        //口味如果有，就插入
        if (flavors != null && flavors.size() > 0){
            for (DishFlavor flavor : flavors) {
                flavor.setDishId(dishId);
                 flavorResult = dishFlavorDao.insert(flavor);
            }
            return flavorResult > 0 ? R.success("添加成功") : R.error("添加失败，稍后重试");
        }
        return dishResult> 0? R.success("添加成功") : R.error("添加失败，稍后重试");
    }

    /**
     * 分页查询
     * @param page
     * @param pageSize
     * @param dishDto
     * @return
     */

    @Override
    public R selectDish(Integer page, Integer pageSize, DishDto dishDto) {


        Page<Dish> dishPage = new Page<>(page, pageSize);
        Page<DishDto> dishDtoPage = new Page<>();
        LambdaQueryWrapper<Dish> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(StringUtils.isNotBlank(dishDto.getName()),Dish::getName,dishDto.getName());
        //      dish表分页数据
        Page<Dish> queryPage = dishDao.selectPage(dishPage, wrapper);
        //      数据拷贝
        BeanUtils.copyProperties(queryPage,dishDtoPage,"records");
        List<DishDto> dtos = queryPage.getRecords().stream().map(dishItem -> {
            Long categoryId = dishItem.getCategoryId();
            Category category = categoryDao.selectById(categoryId);
            DishDto dto = new DishDto();
            dto.setCategoryName(category.getName());
            BeanUtils.copyProperties(dishItem, dto);
            return dto;
        }).collect(Collectors.toList());
        dishDtoPage.setRecords(dtos);
        //Map map =  new HashMap<>();
        //TODO:lambda重写
        /*if (queryPage != null){

            for (Dish record : queryPage.getRecords()) {
                DishDto dto = new DishDto();
                Category category = categoryDao.selectById(record.getCategoryId());
                String categoryName = category.getName();
                dto.setCategoryName(categoryName);
                BeanUtils.copyProperties(record,dto);
                dishDtos.add(dto);
            }
            long total = queryPage.getTotal();

            map.put("records",dishDtos);
            //  这里要强转成int，因为long类型在被转成JSON成会变成string，前端会报错，不能正确显示
            map.put("total",(int)total);



        }


        log.info("要返回的数据:{}",map);

        return R.success(map);*/

        return R.success(dishDtoPage);

    }

    @Override
    public R queryById(Long id) {


        Dish dish = dishDao.selectById(id);
        LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(DishFlavor::getDishId,id);
        List<DishFlavor> flavorList = dishFlavorDao.selectList(wrapper);
        DishDto dishDto = new DishDto();
        dishDto.setFlavors(flavorList);
        BeanUtils.copyProperties(dish,dishDto);


        return R.success(dishDto);
    }

    /**
     * 更新菜品
     * @param dishDto
     * @return
     */
    @Override
    public R updateDish(DishDto dishDto) {

         //增删改操作把之前存Redis的数据删掉，保证数据的同步
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);

        dishDao.deleteById(dishDto.getId());
        if (dishDto.getFlavors().size() != 0){
          Map<String,Object> map =new  HashMap<>();
          map.put("dish_id",dishDto.getId());
            dishFlavorDao.deleteByMap(map);
        }

        dishDto.setId(null);
        int insertDish = dishDao.insert(dishDto);

        int sum = 0;
        List<DishFlavor> flavors = dishDto.getFlavors();
        if (flavors.size() != 0){
            for (DishFlavor flavor : flavors) {
                flavor.setId(null);
                flavor.setDishId(dishDto.getId());
               int insertDishFlavor = dishFlavorDao.insert(flavor);
               sum+= insertDishFlavor;
            }
            if (insertDish > 0 && sum > 0 ){
                return R.success("修改成功");
            }else {
                return R.error("修改失败");
            }

        }
        if (insertDish > 0){
            return R.success("修改成功");
        }

        return R.error("修改失败");
    }

    /**
     * 删除菜品
     * @param list
     * @return
     */
    @Override
    public R deleteDish(List<String> list) {


        //增删改操作把之前存Redis的数据删掉，保证数据的同步
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);

        int deleteDish = 0;

            List<Long> ids = list.stream().map(Long::valueOf).collect(Collectors.toList());
        //    todo：感觉逻辑不对劲，批量删除，若第一个为停售则不能批量删除，若第一个不为停售则能部分删除

            //select count(*) from dish where status = 1 and id in (ids)
            LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
            dishLambdaQueryWrapper.eq(Dish::getStatus,1).in(Dish::getId,ids);
            Integer selectCount = dishDao.selectCount(dishLambdaQueryWrapper);
            if (selectCount == 0) {
                deleteDish = dishDao.deleteBatchIds(ids);


                for (Object id : ids) {
                    LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(DishFlavor::getDishId,id);
                    List<DishFlavor> dishFlavors = dishFlavorDao.selectList(wrapper);
                    if (dishFlavors.size() != 0){
                        HashMap<String, Object> map = new HashMap<>();
                        map.put("dish_id",id);
                        //这里能进行批量删除的原因是他们的dish_id 一样，而<foreach> 循环是用来删除不同id的
                        int deleteDishFlavor = dishFlavorDao.deleteByMap(map);
                        if (deleteDish > 0 && deleteDishFlavor > 0){
                            return R.success("删除成功");
                        }else {
                            return R.error("删除失败");
                        }
                    }
                }
            } else {
                throw new CustomException("售卖中的菜品不能删除");
            }




        return deleteDish > 0 ? R.success("删除成功") : R.error("删除失败");
        //return null;

    }

    /**
     * 启售/停售
     * @param code
     * @param ids
     * @return
     */
    @Override
    public R updateStatus(Integer code, List<Long> ids) {
        //增删改操作把之前存Redis的数据删掉，保证数据的同步
        Set keys = redisTemplate.keys("dish_*");
        redisTemplate.delete(keys);

        LambdaUpdateWrapper<Dish> updateWrapper = new LambdaUpdateWrapper<>();
        if (code == 0 ){
                updateWrapper.set(Dish::getStatus,code);
                updateWrapper.in(Dish::getId,ids);
            int update = dishDao.update(null, updateWrapper);

            /*
            预编译会出现空值
            for (Long id : ids) {

                Dish dish = new Dish();
                dish.setId(id);
                dish.setStatus(code);
                int updateById = dishDao.updateById(dish);
            }*/


            return update > 0 ? R.success("更新成功") : R.error("更新失败");
        }else {
            updateWrapper.set(Dish::getStatus,code);
            updateWrapper.in(Dish::getId,ids);
            int updateById = dishDao.update(null, updateWrapper);
            return updateById > 0 ? R.success("更新成功") : R.error("更新失败");
        }

    }

    /**
     * 客户端查询菜品
     * @param dish
     * @return
     */
    @Override
    public R listDish(DishDto dish) {


        //Category selectById = categoryDao.selectById(category.getId());
        log.info("菜品id:{}",dish.getCategoryId());



        //Redis优化菜品分类下的菜品查询，key(dish_categoryId)
        //key
        String dishRedisKey = "dish_"+dish.getCategoryId();
        //查询Redis里该key里面有木有数据，有，直接返回,没有就存进去
        List<DishDto> dishDtos = (List<DishDto>) redisTemplate.opsForValue().get(dishRedisKey);

        if (dishDtos != null){
            return R.success(dishDtos);
        }


        //status等于空，查询启售和停售的所有菜品
        //status不等于空，查询启售或者停售的所有菜品
        LambdaQueryWrapper<Dish> dishLambdaQueryWrapper = new LambdaQueryWrapper<>();
        dishLambdaQueryWrapper.like(StringUtils.isNotEmpty(dish.getName()),Dish::getName,dish.getName())
                .eq(dish.getCategoryId() != null,Dish::getCategoryId,dish.getCategoryId())
                .eq(dish.getStatus() != null,Dish::getStatus,dish.getStatus());
        //查询出的菜品集合
        List<Dish> dishes = dishDao.selectList(dishLambdaQueryWrapper);
        //这里要封装菜品口味数据
        List<DishDto> dishDtoArrayList = new ArrayList<>();
        for (Dish dis : dishes) {
            //这里要创建新对象，不然都是同一对象，数据都是重复的
            DishDto dishDto = new DishDto();
            LambdaQueryWrapper<DishFlavor> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(dis.getId() != null,DishFlavor::getDishId,dis.getId());
            List<DishFlavor>  dishFlavors = dishFlavorDao.selectList(wrapper);
            BeanUtils.copyProperties(dis,dishDto);
            dishDto.setFlavors(dishFlavors);
            dishDtoArrayList.add(dishDto);
        }
        log.info("dishDtoArrayList集合中的数据：{}",dishDtoArrayList);

        //Redis中没有该key数据，进行存入
        redisTemplate.opsForValue().set(dishRedisKey,dishDtoArrayList);


        return R.success(dishDtoArrayList);
    }
}
